package com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.core;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.PageUtils;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.TinyShardingAsyncService;
import com.tinyshardingjdbc.tinyshardingjdbc.shardingasync.annotaion.TinyShardingJdbcVo;
import org.apache.ibatis.plugin.Invocation;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;


public class YearProcessor implements TypeProcessor {


    @Override
    public List<String> getTableName(String tableStart, String tableEndDate, String tablePrefix, String fileValue, TinyShardingJdbcVo tinyShardingJdbcVo, Invocation invocation) {
        List<String> responseDTO = PageUtils.getTableNameY(tableStart, tableEndDate, tablePrefix);
        /**
         * 存证关键字,只使用当前的表
         *
         * */
        if (!StringUtils.isBlank(fileValue)) {
            List<String> list = new ArrayList<>();
            list.add(tablePrefix + "_" + fileValue.replace("-", "").substring(0, 4));
            return list;
        }
        return responseDTO;
    }


    @Override
    public String getTableNameSuffix(String fileValue, TinyShardingJdbcVo tinyShardingJdbcVo, Invocation invocation) {
        return String.valueOf(fileValue).replace("-", "").substring(0, 4);
    }


    @SuppressWarnings("all")
    @Override
    public Object orderByProcessor(TinyShardingAsyncService shardingAsyncService, HashMap<String, Long> totalCountMap,
                                         List<String> table,
                                         String tablePrefix,
                                         String doDataSql,
                                         IPage<?> page,
                                         long totalCount) {

        long pageStart = (page.getPages() - 1) * page.getSize();
        long pageEnd = page.getPages() * page.getSize();
        long tableCountIndex = 0;
        List<Future<Object>> futureList = new ArrayList<>();

        /**
         * 应该在排序处理 简单做个表排序---某种情况符合按照年月分表的逻辑并不适合其他
         *
         * */
        if(doDataSql.toUpperCase().contains("ORDER BY")){
            table.sort(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    if(doDataSql.toUpperCase().contains("DESC")){
                        return o2.compareTo(o1);
                    }
                    return o1.compareTo(o2);
                }
            });
        }


        for (String tableName : table) {
            long tableCount = totalCountMap.get(tableName);
            tableCountIndex += tableCount;
            if (tableCountIndex < pageStart) {
                continue;
            }
            long limitIndex;
            long limitNum;
            if (tableCountIndex < pageEnd) {
                limitNum = tableCountIndex - pageStart;
                limitIndex = tableCount - limitNum;
                pageStart += limitNum;
                String optSql = doDataSql.split("LIMIT")[0];
                optSql = optSql.replace(tablePrefix, tableName) + "limit " + limitIndex + "," + limitNum;
                Future<Object> asyncQueryPage = shardingAsyncService.asyncQueryPage(optSql);
                futureList.add(asyncQueryPage);
            } else {
                limitIndex = pageStart - (tableCountIndex - tableCount);
                if (limitIndex < 0) {
                    limitIndex = 0;
                }
                limitNum = pageEnd - pageStart;
                String optSql = doDataSql.split("LIMIT")[0];
                optSql = optSql.replace(tablePrefix, tableName) + " limit " + limitIndex + "," + limitNum;
                Future<Object> asyncQueryPage = shardingAsyncService.asyncQueryPage(optSql);
                futureList.add(asyncQueryPage);
                break;
            }
        }
        List<Object> entityList = new ArrayList<>();
        for (Future<Object> future : futureList) {
            try {
                List<Object> asyncQueryPageList = (List<Object>) future.get(120, TimeUnit.SECONDS);
                for (Object os : asyncQueryPageList) {
                    entityList.add(os);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


        return entityList;
    }
}
